package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.client.ItemApi;
import com.hmall.common.client.UserClient;
import com.hmall.common.entity.Address;
import com.hmall.common.entity.Item;
import com.hmall.common.utils.SnowFlake;
import com.hmall.common.utils.SnowFlakeComponent;
import com.hmall.order.context.BaseContext;
import com.hmall.order.mapper.OrderDetailMapper;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDTO;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.service.IOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.UUID;

@Service
@Slf4j
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private OrderLogisticsMapper orderLogisticsMapper;

    @Autowired
    private ItemApi itemClient;

    @Autowired
    private UserClient userClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 提交订单
     *
     * @param orderDTO 订购 DTO
     * @return {@link Long}
     */
    @Override
    @GlobalTransactional
    public Long commitOrder(OrderDTO orderDTO) {

        // 通过雪花算法得到订单id
        SnowFlake instance = SnowFlakeComponent.getInstance();
        Long id = instance.nextId();
        // feignClient远程调用
        Item item = itemClient.findItemById(orderDTO.getItemId());
        Integer num = orderDTO.getNum();
        Long price = item.getPrice();
        Long value = num.longValue();
        // 总费用
        Long totalFee = price * value;
        Order order = Order.builder()
                .status(1)
                .totalFee(totalFee)
                .paymentType(orderDTO.getPaymentType())
                .userId(BaseContext.getCurrentId())
                .createTime(new Date())
                .updateTime(new Date())
                .id(id)
                .build();
        // 插入订单数据
        orderMapper.insert(order);

        OrderDetail orderDetail = OrderDetail.builder()
                .orderId(id)
                .createTime(new Date())
                .updateTime(new Date())
                .image(item.getImage())
                .num(orderDTO.getNum())
                .itemId(item.getId())
                .name(item.getName())
                .price(totalFee).build();
        // 插入订单细节数据
        orderDetailMapper.insert(orderDetail);
        // 远程调用userClient获得地址
        Address address = userClient.getAddressById(orderDTO.getAddressId());
        OrderLogistics orderLogistics = OrderLogistics.builder()
                .orderId(id)
                .contact(address.getContact())
                .mobile(address.getMobile())
                .province(address.getProvince())
                .city(address.getCity())
                .town(address.getTown())
                .street(address.getStreet())
                .createTime(new Date())
                .updateTime(new Date()).build();
        orderLogisticsMapper.insert(orderLogistics);
        // 直接新建一个item实体类
        Item newItem = new Item();
        // 得到具体id
        newItem.setId(item.getId());
        // 修改库存
        newItem.setStock(item.getStock() - num);
        // 直接远程调用itemClient进行库存的修改
        itemClient.modifyItem(newItem);

        // 延迟消息的发送
        Message message = MessageBuilder.withBody(String.valueOf(id).getBytes())
                .setHeader("x-delay", 3000)
                .build();

        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend("DarkMall.delay.direct", "delay", message, correlationData);
        log.info("------发送延迟消息，接收到订单id：{}-------", id);
        return id;


    }
}
